﻿using System.Windows.Controls.DataVisualization.Charting;
using System.Data.Services.Client;
using Tfs.OnTheRoad.Model;
using System;
using System.Linq;
using System.Windows;
using Tfs.OnTheRoad.ViewModel;
using System.Windows.Media.Animation;
namespace Tfs.OnTheRoad.Controls.ChartStrategies
{
    /// <summary>
    /// Interface that describes how a List View Model should behave
    /// </summary>
    public abstract class BaseChartStrategy
    {
        public BaseChartStrategy()
        {
            Field1 = "State";
            Field2 = "Type";
        }
        protected ISeries Serie { get; private set; }
        public void SetupChart(Chart chartToSetup, WorkItemsSummaryList chartData)
        {
            Serie = CreateChartSerie(chartData);
            chartToSetup.LegendTitle = Field1;
            chartToSetup.Series.Clear();
            chartToSetup.Series.Add(Serie);
            chartToSetup.Loaded += new RoutedEventHandler(chartToSetup_Loaded);
            chartToSetup.Visibility = System.Windows.Visibility.Visible;                    
        }
        
        void chartToSetup_Loaded(object sender, RoutedEventArgs e)
        {
            AdjustAfterLoaded();
        }

        public virtual void AdjustAfterLoaded()
        {
        }
        protected abstract ISeries CreateChartSerie(WorkItemsSummaryList chartData);
        public string Field1{ get; set; }
        public string Field2{ get; set; }
        /// <summary>
        /// IsStacked means if the Field2 should be used or not
        /// </summary>
        public virtual bool IsStacked
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Fields which will be used on the OData Select call
        /// </summary>
        public string SelectFields {
            get
            {
                string toReturn;
                if (IsStacked)
                {
                    toReturn = string.Format("{0},{1}", Field1, Field2);
                    //We always include the Type to group the WI Overview Window
                    if (string.Compare(Field1, "Type", StringComparison.OrdinalIgnoreCase) != 0 &&
                        string.Compare(Field2, "Type", StringComparison.OrdinalIgnoreCase) != 0)
                        toReturn += ",Type";
                }
                else
                {
                    toReturn = Field1;
                    //We always include the Type to group the WI Overview Window
                    if (string.Compare(Field1, "Type", StringComparison.OrdinalIgnoreCase) != 0)
                        toReturn += ",Type";
                }
             
                return toReturn;
            }
        }

        protected void AdjustAxis(IAxis axisToAdjust)
        {
            DateTimeAxis dateAxis = axisToAdjust as DateTimeAxis;
            if (dateAxis != null)
            {
                var labelStyle = new Style(typeof(DateTimeAxisLabel));
                labelStyle.Setters.Add(new Setter(DateTimeAxisLabel.StringFormatProperty, "{0:dd.MM.yy}"));
                dateAxis.IntervalType = DateTimeIntervalType.Days;
                dateAxis.AxisLabelStyle = labelStyle;
            }
        }
    }

    public abstract class BaseDataPointChartStrategy<DataPointChartType> : BaseChartStrategy
        where DataPointChartType:DataPointSeries
    {
        protected override ISeries CreateChartSerie(WorkItemsSummaryList chartData)
        {
            DataPointChartType toReturn = System.Activator.CreateInstance<DataPointChartType>();
            toReturn.SelectionChanged += new System.Windows.Controls.SelectionChangedEventHandler(toReturn_SelectionChanged);
            toReturn.ItemsSource = chartData;
            toReturn.IsSelectionEnabled = true;
            toReturn.IndependentValuePath = "Caption";
            toReturn.DependentValuePath = "Count";
            toReturn.Title = Field1;
            toReturn.AnimationSequence = AnimationSequence.FirstToLast;
            toReturn.TransitionEasingFunction = new ElasticEase() { EasingMode = EasingMode.EaseInOut };
            return toReturn;
        }

        void toReturn_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            Tfs.OnTheRoad.Commands.NavigateToWorkItemsOverviewCommand cmd = new Commands.NavigateToWorkItemsOverviewCommand();
            cmd.Execute(e);
            ((DataPointChartType)Serie).SelectedItem = null;
        }

        public override void AdjustAfterLoaded()
        {
             //var genArgs = Serie.GetType().GetGenericArguments();
             //Easiest way to check... Otherwise, as the LineAreaBaseSeries<> is a generic type it makes harder
            if (Serie.GetType().GetProperty("ActualDependentRangeAxis")!=null)
                //genArgs.Length == 1 && typeof(LineAreaBaseSeries<>).MakeGenericType(genArgs).IsAssignableFrom(Serie.GetType()))
            {
                AdjustAxis((IAxis)Serie.GetType().GetProperty("ActualDependentRangeAxis").GetValue(Serie,null));
                AdjustAxis((IAxis)Serie.GetType().GetProperty("ActualIndependentAxis").GetValue(Serie, null));
            }
        }
    }

    public class PieChartStrategy : BaseDataPointChartStrategy<PieSeries> 
    {
        public override string ToString()
        {
            return "Pie";
        }
    }
    public class ColumnChartStrategy : BaseDataPointChartStrategy<ColumnSeries> 
    {
        public override string ToString()
        {
            return "Column";
        }
    }
    public class BarChartStrategy : BaseDataPointChartStrategy<BarSeries> {
        public override string ToString()
        {
            return "Bar";
        }
    }
    public class AreaChartStrategy : BaseDataPointChartStrategy<AreaSeries> {
        public override string ToString()
        {
            return "Area";
        }
    }
    public class LineChartStrategy : BaseDataPointChartStrategy<LineSeries> {
        public override string ToString()
        {
            return "Line";
        }
    }
    public class ScatterChartStrategy : BaseDataPointChartStrategy<ScatterSeries> {
        public override string ToString()
        {
            return "Scatter";
        }
    }


    public abstract class BaseStackedChartStrategy<StackedChartType> : BaseChartStrategy
        where StackedChartType: DefinitionSeries
    {
        public override bool IsStacked
        {
            get
            {
                return true;
            }
        }
        protected override ISeries CreateChartSerie(WorkItemsSummaryList chartData)
        {
            StackedChartType toReturn = System.Activator.CreateInstance<StackedChartType>();
            toReturn.SelectionChanged+=new System.Windows.Controls.SelectionChangedEventHandler(Serie_SelectionChanged);
            toReturn.SelectionMode = SeriesSelectionMode.Single;
            
            foreach (var item in chartData)
            {
                SeriesDefinition serieItem = new SeriesDefinition();
                serieItem.ItemsSource = item.Items;
                serieItem.Title = item.Caption;
                serieItem.DependentValuePath = "Count";
                serieItem.IndependentValuePath = "ChildLevel";
                toReturn.SeriesDefinitions.Add(serieItem);
            }
            return toReturn;
        }

        void Serie_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            ((StackedChartType)Serie).SelectedIndex = -1;
            Tfs.OnTheRoad.Commands.NavigateToWorkItemsOverviewCommand cmd = new Commands.NavigateToWorkItemsOverviewCommand();
            cmd.Execute(e);
        }

        public override void AdjustAfterLoaded()
        {
            //Fixing axis
            AdjustAxis(((StackedChartType)Serie).ActualDependentAxis);
            AdjustAxis(((StackedChartType)Serie).ActualIndependentAxis);
        }
    }
    public class StackedColumnChartStrategy : BaseStackedChartStrategy<StackedColumnSeries> {
        public override string ToString()
        {
            return "Stacked Column";
        }
    }
    public class Stacked100ColumnChartStrategy : BaseStackedChartStrategy<Stacked100ColumnSeries> {
        public override string ToString()
        {
            return "Stacked % Column";
        }
    }
    public class StackedBarChartStrategy : BaseStackedChartStrategy<StackedBarSeries> {
        public override string ToString()
        {
            return "Stacked Bar";
        }
    }
    public class Stacked100BarChartStrategy : BaseStackedChartStrategy<Stacked100BarSeries> {
        public override string ToString()
        {
            return "Stacked % Bar";
        }
    }
    public class StackedLineSeriesChartStrategy : BaseStackedChartStrategy<StackedLineSeries> {
        public override string ToString()
        {
            return "Stacked Line";
        }
    }
    public class Stacked100LineChartStrategy : BaseStackedChartStrategy<Stacked100LineSeries> {
        public override string ToString()
        {
            return "Stacked % Line";
        }
    }
    public class StackedAreaChartStrategy : BaseStackedChartStrategy<StackedAreaSeries> {
        public override string ToString()
        {
            return "Stacked Area";
        }
    }
    public class Stacked100AreaChartStrategy : BaseStackedChartStrategy<Stacked100AreaSeries> {
        public override string ToString()
        {
            return "Stacked % Area";
        }
    }
}

